package cn.b.sky.mes.em.service.impl;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import cn.b.sky.mes.em.enums.MaintainTaskStatus;
import cn.b.sky.mes.em.enums.StrategyType;
import cn.b.sky.mes.em.enums.TimeUnitCode;
import cn.b.sky.mes.em.model.MaintainConfig;
import cn.b.sky.mes.em.model.MaintainTaskCause;
import org.springframework.stereotype.Service;

import cn.b.sky.mes.em.dao.MaintainTaskDao;
import cn.b.sky.mes.em.model.MaintainTask;
import cn.b.sky.mes.em.model.MaintainTaskPart;
import cn.b.sky.mes.em.model.condition.MaintainTaskCondition;
import cn.b.sky.mes.em.service.MaintainConfigService;
import cn.b.sky.mes.em.service.MaintainTaskService;
import cn.b.sky.mes.em.utils.LikeHashMap;
import cn.b.sky.common.model.BatchJobReport;
import org.apache.commons.lang3.StringUtils;
import cn.b.sky.i18n.utils.LocaleResourceBundle;
import cn.b.sky.user.SecurityContextUtil;
import cn.b.sky.mes.cm.enums.ECodeEnums;
import cn.b.sky.user.service.ECodeService;
import cn.b.sky.user.service.NumberRuleService;
import cn.b.sky.user.service.model.ECode;

@Service("maintainTaskService")
public class MaintainTaskServiceImpl implements MaintainTaskService {

  @Resource
  MaintainConfigService maintainConfigService;

  @Resource
  MaintainTaskDao maintainTaskDao;

  @Resource
  NumberRuleService numberRuleService;

  @Resource
  private ECodeService eCodeService;

  @Override
  public void doCreateCycleMaintainTaskJob() {
    Date now = new Date();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    now = df.parse(df.format(now), new ParsePosition(0));
    // 查询配置列表
    List<MaintainConfig> configList = maintainConfigService.selectMaintainConfigByStrategyType(StrategyType.CYCLE
        .getValue());
    for (MaintainConfig config : configList) {
      Date prevDate = config.getPrevMaintainDate();
      while (true) {
        prevDate = getDateByConfig(prevDate, config);
        if (prevDate.before(now)) {
          continue;
        } else {
          MaintainTask maintainTask = new MaintainTask();
          maintainTask.setSiteCode(config.getSiteCode());
          maintainTask.setEquipmentCode(config.getEquipmentCode());
          maintainTask.setStrategyCode(config.getStrategyCode());
          maintainTask.setPlannedMaintainDate(prevDate);
          // 判断任务是否已经存在
          MaintainTask task = maintainTaskDao.selectMaintainTask(maintainTask);
          if (task == null) {
            maintainTask.setStatusECode(MaintainTaskStatus.PLAN.getValue());
            maintainTask.setUnPlannedFlag(0);
            maintainTask.setCreateUser("SYSTEM");
            maintainTask.setCreateDateTime(new Date());
            maintainTask.setModifyUser("SYSTEM");
            maintainTask.setModifyDateTime(new Date());
            maintainTask.setTaskCode(numberRuleService.selectNextNumber(config.getSiteCode(), "MAINTAINTASKCODE"));
            maintainTaskDao.insertMaintainTask(maintainTask);
            config.setNextMaintainDate(prevDate);
            maintainConfigService.updateMaintainConfigUsedByTask(config);
          }
          break;
        }
      }

    }
  }

  @Override
  public void doCreateCountMaintainTaskJob() {
    // 查询配置列表
    List<MaintainConfig> configList = maintainConfigService.selectMaintainConfigByStrategyType(StrategyType.COUNT
        .getValue());
    for (MaintainConfig config : configList) {
      if (config.getCurrCountValue() >= config.getStrategyCountValue()) {
        long count = config.getCurrCountValue() - config.getStrategyCountValue();
        MaintainTask maintainTask = new MaintainTask();
        maintainTask.setSiteCode(config.getSiteCode());
        maintainTask.setEquipmentCode(config.getEquipmentCode());
        maintainTask.setStrategyCode(config.getStrategyCode());
        maintainTask.setPlannedMaintainDate(new Date());
        maintainTask.setStatusECode(MaintainTaskStatus.PLAN.getValue());
        maintainTask.setUnPlannedFlag(0);
        maintainTask.setCreateUser("SYSTEM");
        maintainTask.setCreateDateTime(new Date());
        maintainTask.setModifyUser("SYSTEM");
        maintainTask.setModifyDateTime(new Date());
        maintainTask.setTaskCode(numberRuleService.selectNextNumber(config.getSiteCode(), "MAINTAINTASKCODE"));
        maintainTaskDao.insertMaintainTask(maintainTask);
        config.setCurrCountValue(count);
        config.setNextMaintainDate(maintainTask.getPlannedMaintainDate());
        maintainConfigService.updateMaintainConfigUsedByTask(config);
      }
    }
  }

  /**
   * 
   * <strong>Title : getDateByConfig<br>
   * </strong> <strong>Description : </strong>根据配置计算下次维护时间<br>
   * <strong>Create on : 2015-11-10 上午09:51:01<br>
   * </strong>
   * <p>
   * 
   * @param date
   * @param config
   * @return Date
   * @throws
   * @author zhaoxin01<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   *          <strong>修改历史:</strong><br>
   *          修改人 | 修改日期 | 修改描述<br>
   *          -------------------------------------------<br>
   * <br>
   * <br>
   */
  private Date getDateByConfig(Date date, MaintainConfig config) {
    Date returnDate = null;
    String type = config.getTimeUnitECode();
    int day = config.getMaintainDayOfMonth();
    int value = Integer.parseInt(config.getStrategyTimeValue().toString());
    if (type.equals(TimeUnitCode.DAY.getValue())) {
      returnDate = getSysDate(date, 0, 0, value);
    } else if (type.equals(TimeUnitCode.MONTH.getValue())) {
      returnDate = getSysDate(date, 0, value, 0);
      returnDate = getDateForMonth(returnDate, day);
    } else if (type.equals(TimeUnitCode.QUARTER.getValue())) {
      returnDate = getSysDate(date, 0, value * 3, 0);
      returnDate = getDateForMonth(returnDate, day);
    } else if (type.equals(TimeUnitCode.YEAR.getValue())) {
      returnDate = getSysDate(date, value, 0, 0);
      returnDate = getDateForMonth(returnDate, day);
    }
    return returnDate;

  }

  /**
   * 
   * <strong>Title : GetDateForMonth<br>
   * </strong> <strong>Description : </strong>根据配置修正日期<br>
   * <strong>Create on : 2015-11-10 上午09:50:14<br>
   * </strong>
   * <p>
   * 
   * @param date
   * @param day
   * @return Date
   * @throws
   * @author zhaoxin01<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   *          <strong>修改历史:</strong><br>
   *          修改人 | 修改日期 | 修改描述<br>
   *          -------------------------------------------<br>
   * <br>
   * <br>
   */
  private Date getDateForMonth(Date date, int day) {
    Calendar cld = Calendar.getInstance();
    cld.setTime(date);
    if (cld.get(Calendar.DAY_OF_MONTH) < day) {
      int dayOfMonth = cld.getActualMaximum(Calendar.DAY_OF_MONTH);
      int days = dayOfMonth - cld.get(Calendar.DAY_OF_MONTH);
      cld.add(Calendar.DATE, days);
      return cld.getTime();
    } else {
      return date;
    }
  }

  /**
   * 
   * <strong>Title : GetSysDate<br>
   * </strong> <strong>Description : </strong>累加日期<br>
   * <strong>Create on : 2015-11-10 上午09:49:46<br>
   * </strong>
   * <p>
   * 
   * @param date
   *            日期
   * @param year
   *            年
   * @param month
   *            月
   * @param day
   *            日
   * @return Date
   * @throws
   * @author zhaoxin01<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   *          <strong>修改历史:</strong><br>
   *          修改人 | 修改日期 | 修改描述<br>
   *          -------------------------------------------<br>
   * <br>
   * <br>
   */
  private Date getSysDate(Date date, int year, int month, int day) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    if (day != 0) {
      cal.add(Calendar.DATE, day);
    }
    if (month != 0) {
      cal.add(Calendar.MONTH, month);
    }
    if (year != 0) {
      cal.add(Calendar.YEAR, year);

    }
    return cal.getTime();
  }

  @Override
  public MaintainTask selectMaintainTask(MaintainTask maintainTask) {
    return maintainTaskDao.selectMaintainTask(maintainTask);
  }

  @Override
  public void insertMaintainTask(MaintainTask maintainTask) {
    maintainTask.setTaskCode(numberRuleService.selectNextNumber(maintainTask.getSiteCode(), "MAINTAINTASKCODE"));
    maintainTaskDao.insertMaintainTask(maintainTask);

  }

  @Override
  public void deleteMaintainTaskByStatus(String siteCode, String equipmentCode, String strategyCode, String statusECode) {
    maintainTaskDao.deleteMaintainTaskByStatus(siteCode, equipmentCode, strategyCode, statusECode);

  }

  @Override
  public List<MaintainTask> selectMaintainTaskByCondition(MaintainTaskCondition maintainTaskCondition) {
    return maintainTaskDao.selectMaintainTaskByCondition(maintainTaskCondition);
  }

  @Override
  public int selectMaintainTaskCount(MaintainTaskCondition maintainTaskCondition) {
    return maintainTaskDao.selectMaintainTaskCount(maintainTaskCondition);
  }

  @Override
  public MaintainTask selectMaintainTaskByCode(String siteCode, String taskCode) {
    return maintainTaskDao.selectMaintainTaskByCode(siteCode, taskCode);
  }

  @Override
  public void updateMaintainTask(MaintainTask maintainTask, List<MaintainTaskCause> causes, List<MaintainTaskPart> parts) {
    maintainTask.setStatusECode(MaintainTaskStatus.EXECUTE.getValue());
    maintainTaskDao.updateMaintainTask(maintainTask);
    maintainTaskDao.deleteMaintainTaskCause(maintainTask.getSiteCode(), maintainTask.getTaskCode());
    maintainTaskDao.deleteMaintainTaskPart(maintainTask.getSiteCode(), maintainTask.getTaskCode());
    if (causes != null) {
      for (MaintainTaskCause c : causes) {
        maintainTaskDao.insertMaintainTaskCause(c);
      }
    }
    if (parts != null) {
      for (MaintainTaskPart p : parts) {
        maintainTaskDao.insertMaintainTaskPart(p);
      }
    }
  }

  @Override
  public List<MaintainTaskCause> selectMaintainTaskCauseList(String siteCode, String taskCode) {
    return maintainTaskDao.selectMaintainTaskCauseList(siteCode, taskCode);
  }

  @Override
  public List<MaintainTaskPart> selectMaintainTaskPartList(String siteCode, String taskCode) {
    return maintainTaskDao.selectMaintainTaskPartList(siteCode, taskCode);
  }

  @Override
  public BatchJobReport doExecuteMaintainTask(String siteCode, String taskCode) {
    String cause = "";
    Boolean success = true;
    MaintainTask task = maintainTaskDao.selectMaintainTaskByCode(siteCode, taskCode);
    if (task.getStatusECode().equals(MaintainTaskStatus.PLAN.getValue())) {
      task.setModifyUser(SecurityContextUtil.getCurrentUserName());
      task.setModifyDateTime(new Date());
      task.setStatusECode(MaintainTaskStatus.EXECUTE.getValue());
      maintainTaskDao.updateMaintainTaskStatus(task);
      // 回写维护配置的上次执行时间
      if (task.getUnPlannedFlag() == 0) {
        Date now = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        now = df.parse(df.format(now), new ParsePosition(0));
        MaintainConfig maintainConfig = new MaintainConfig();
        maintainConfig.setSiteCode(siteCode);
        maintainConfig.setEquipmentCode(task.getEquipmentCode());
        maintainConfig.setStrategyCode(task.getStrategyCode());
        maintainConfig.setPrevMaintainDate(task.getPlannedMaintainDate());
        maintainConfig.setModifyUser(SecurityContextUtil.getCurrentUserName());
        maintainConfig.setModifyDateTime(new Date());
        maintainConfigService.updatePrevMaintainDate(maintainConfig);
      }
      // 更新开始时间
      task.setMaintainStartDateTime(new Date());
      maintainTaskDao.updateMaintainTask(task);
    } else {
      cause = LocaleResourceBundle.getCommonResourceLabel(SecurityContextUtil.getSiteCode(),
          SecurityContextUtil.getLanguageCode(), "executeMaintainTaskFail.M");
      success = false;
    }

    return new BatchJobReport(taskCode, cause, success);
  }

  @Override
  public BatchJobReport doCancelMaintainTask(String siteCode, String taskCode) {
    String cause = "";
    Boolean success = true;
    MaintainTask task = maintainTaskDao.selectMaintainTaskByCode(siteCode, taskCode);
    if (task.getStatusECode().equals(MaintainTaskStatus.PLAN.getValue())) {
      task.setModifyUser(SecurityContextUtil.getCurrentUserName());
      task.setModifyDateTime(new Date());
      task.setStatusECode(MaintainTaskStatus.CANCEL.getValue());
      maintainTaskDao.updateMaintainTaskStatus(task);
    } else {
      cause = LocaleResourceBundle.getCommonResourceLabel(SecurityContextUtil.getSiteCode(),
          SecurityContextUtil.getLanguageCode(), "cancelMaintainTaskFail.M");
      success = false;
    }

    return new BatchJobReport(taskCode, cause, success);
  }

  @Override
  public List<MaintainTask> selectMaintainTaskByDate(MaintainTask maintainTask, Date beginDate, Date endDate) {
    List<MaintainTask> tasks = null;
    Date now = new Date();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    now = df.parse(df.format(now), new ParsePosition(0));
    if (maintainTask.getPlannedMaintainDate().before(now)) {
      // 历史时间查询数据库记录即可
      tasks = maintainTaskDao.selectMaintainTaskByDate(maintainTask);
    } else {
      Map<String, MaintainTask> map = new HashMap<String, MaintainTask>();
      LikeHashMap taskMap = calculateTask(beginDate, endDate);
      // 今天及未来日期需要推算
      List<MaintainTask> ts = maintainTaskDao.selectMaintainTaskByDate(maintainTask);
      if (ts != null) {
        for (MaintainTask t : ts) {
          if (StringUtils.isEmpty(t.getStrategyTypeECode())
              || t.getStrategyTypeECode().equals(StrategyType.COUNT.getValue())) {
            String key = df.format(t.getPlannedMaintainDate()) + "&" + t.getSiteCode() + "&" + t.getEquipmentCode()
                + "&" + t.getStrategyCode() + "&" + t.getTaskCode();
            map.put(key, t);
          } else {
            String key = df.format(t.getPlannedMaintainDate()) + "&" + t.getSiteCode() + "&" + t.getEquipmentCode()
                + "&" + t.getStrategyCode();
            map.put(key, t);
          }
        }
      }
      if (taskMap != null) {
        List<Object> cts = taskMap.get(
            df.format(maintainTask.getPlannedMaintainDate()) + "&" + maintainTask.getSiteCode(), true);
        for (Object o : cts) {
          MaintainTask m = (MaintainTask) o;
          String key = df.format(m.getPlannedMaintainDate()) + "&" + m.getSiteCode() + "&" + m.getEquipmentCode() + "&"
              + m.getStrategyCode();
          if ((maintainTask.getStatusECode() == null || m.getStatusECode().equals(maintainTask.getStatusECode()))
              && !map.containsKey(key)) {
            map.put(key, m);
          }

        }
      }
      tasks = new ArrayList<MaintainTask>();
      Iterator iter = map.entrySet().iterator();
      while (iter.hasNext()) {
        Entry entry = (Entry) iter.next();
        MaintainTask val = (MaintainTask) entry.getValue();
        tasks.add(val);
      }

    }
    return tasks;
  }

  public LikeHashMap calculateTask(Date beginDate, Date endDate) {
    LikeHashMap map = new LikeHashMap();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    /*Date now = new Date();
    now = df.parse(df.format(now), new ParsePosition(0));
    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.YEAR, 1);
    Date lastDate = df.parse(df.format(cal.getTime()), new ParsePosition(0));*/
    ECode ecode = eCodeService.selectEcodeByECodeTypeAndLanguageCodeAndECode(MaintainTaskStatus.PLAN.getValue(),
        ECodeEnums.MAINTAINTASKSTATUS.getCode(), SecurityContextUtil.getLanguageCode());
    String statusText = ecode.geteCodeText();
    // 查询配置列表
    List<MaintainConfig> configList = maintainConfigService.selectMaintainConfigByStrategyType(StrategyType.CYCLE
        .getValue());
    for (MaintainConfig config : configList) {
      Date prevDate = config.getPrevMaintainDate();
      while (true) {
        prevDate = getDateByConfig(prevDate, config);
        if (prevDate.after(endDate)) {
          break;
        }
        if (prevDate.before(beginDate)) {
          continue;
        } else {
          MaintainTask maintainTask = new MaintainTask();
          maintainTask.setSiteCode(config.getSiteCode());
          maintainTask.setEquipmentCode(config.getEquipmentCode());
          maintainTask.setEquipmentText(config.getEquipmentText());
          maintainTask.setStrategyCode(config.getStrategyCode());
          maintainTask.setStrategyText(config.getStrategyText());
          maintainTask.setPlannedMaintainDate(prevDate);
          maintainTask.setStatusECode(MaintainTaskStatus.PLAN.getValue());
          maintainTask.setStatusECodeText(statusText);
          maintainTask.setUnPlannedFlag(0);
          maintainTask.setTaskCode("待生成");
          String key = df.format(prevDate) + "&" + config.getSiteCode() + "&" + config.getEquipmentCode() + "&"
              + config.getStrategyCode();
          map.put(key, maintainTask);
        }
      }
    }
    return map;
  }

  @Override
  public List<MaintainTask> selectMaintainTaskCountForCal(String siteCode, Date beginDate, Date endDate) {
    List<MaintainTask> result = new ArrayList<MaintainTask>();
    List<Date> dates = getDatesBetweenTwoDate(beginDate, endDate);
    for (Date d : dates) {
      MaintainTask task = new MaintainTask();
      task.setSiteCode(siteCode);
      task.setLanguageCode(SecurityContextUtil.getLanguageCode());
      task.setStatusECodeType(ECodeEnums.MAINTAINTASKSTATUS.getCode());
      task.setPlannedMaintainDate(d);
      List<MaintainTask> tasks = selectMaintainTaskByDate(task, beginDate, endDate);
      int count = 0;
      if (tasks != null) {
        count = tasks.size();
      }
      if (count > 0) {
        MaintainTask r = new MaintainTask();
        r.setPlannedMaintainDate(d);
        r.setCount(count);
        result.add(r);
      }
    }
    return result;
  }

  public List<Date> getDatesBetweenTwoDate(Date beginDate, Date endDate) {
    List<Date> lDate = new ArrayList<Date>();
    lDate.add(beginDate);// 把开始时间加入集合
    Calendar cal = Calendar.getInstance();
    // 使用给定的 Date 设置此 Calendar 的时间
    cal.setTime(beginDate);
    boolean bContinue = true;
    while (bContinue) {
      // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
      cal.add(Calendar.DAY_OF_MONTH, 1);
      // 测试此日期是否在指定日期之后
      if (endDate.after(cal.getTime())) {
        lDate.add(cal.getTime());
      } else {
        break;
      }
    }
    lDate.add(endDate);// 把结束时间加入集合
    return lDate;
  }

  @Override
  public MaintainTask selectMaintainTaskCountDeatilForCal(String siteCode, Date day) {
    MaintainTask result = new MaintainTask();
    MaintainTask task = new MaintainTask();
    task.setSiteCode(siteCode);
    task.setLanguageCode(SecurityContextUtil.getLanguageCode());
    task.setStatusECodeType(ECodeEnums.MAINTAINTASKSTATUS.getCode());
    task.setPlannedMaintainDate(day);
    List<MaintainTask> details = selectMaintainTaskByDate(task, day, day);
    if (details != null) {
      result.setTotal(details.size());
    } else {
      result.setTotal(0);
    }
    task.setStatusECode(MaintainTaskStatus.PLAN.getValue());
    details = selectMaintainTaskByDate(task, day, day);
    if (details != null) {
      result.setPlan(details.size());
    } else {
      result.setPlan(0);
    }
    task.setStatusECode(MaintainTaskStatus.EXECUTE.getValue());
    details = selectMaintainTaskByDate(task, day, day);
    if (details != null) {
      result.setExecute(details.size());
    } else {
      result.setExecute(0);
    }
    task.setStatusECode(MaintainTaskStatus.CANCEL.getValue());
    details = selectMaintainTaskByDate(task, day, day);
    if (details != null) {
      result.setCancel(details.size());
    } else {
      result.setCancel(0);
    }
    task.setStatusECode(MaintainTaskStatus.DONE.getValue());
    details = selectMaintainTaskByDate(task, day, day);
    if (details != null) {
      result.setDone(details.size());
    } else {
      result.setDone(0);
    }
    return result;
  }

  @Override
  public void doSubmitMaintainTask(MaintainTask maintainTask, List<MaintainTaskCause> causes,
      List<MaintainTaskPart> parts) {
    maintainTask.setStatusECode(MaintainTaskStatus.DONE.getValue());
    maintainTaskDao.updateMaintainTask(maintainTask);
    maintainTaskDao.deleteMaintainTaskCause(maintainTask.getSiteCode(), maintainTask.getTaskCode());
    maintainTaskDao.deleteMaintainTaskPart(maintainTask.getSiteCode(), maintainTask.getTaskCode());
    if (causes != null) {
      for (MaintainTaskCause c : causes) {
        maintainTaskDao.insertMaintainTaskCause(c);
      }
    }
    if (parts != null) {
      for (MaintainTaskPart p : parts) {
        maintainTaskDao.insertMaintainTaskPart(p);
      }
    }

  }

}
